home *** CD-ROM | disk | FTP | other *** search
- /*•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
- /* Offscreen.c
- /*
- /* Yet another offscreen drawing module that uses GWorld to eliminate drawing flicker.
- /*
- /* Author: Michael Chen, Human Interface Group / ATG
- /* Copyright © 1991-1993 Apple Computer, Inc. All rights reserved.
- /*
- /* Part of Virtual Sphere Sample Code Release v1.1
- /*•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••*/
-
- #ifndef __OFFSCREEN__
- #include "Offscreen.h"
- #endif
-
- #ifndef __QDOFFSCREEN__
- #include <QDOffscreen.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- /* Local globals for this file (module) only */
- static CGrafPtr lgSavedPort = nil;
- static GDHandle lgSavedGDH = nil;
- static Boolean lgRunningSystem7 = false;
-
- /*=================================================================================================
- /* InitializeOffscreen
- /*
- /* Must be called before any other routines in this module.
- /* Check for availibility of GWorld. GWorld exists if we are running
- /* System 7 or if 32-bit QuickDraw is installed.
- /*-------------------------------------------------------------------------------------------------*/
- pascal OSErr InitializeOffscreen (Boolean *gWorldAvailable)
- {
- OSErr err;
- long gestaltResponse;
-
- *gWorldAvailable = false;
-
- /* Check for System 7 */
- err = Gestalt (gestaltSystemVersion, &gestaltResponse);
- if (err != noErr) return (err);
- lgRunningSystem7 = (gestaltResponse & 0xF00) == 0x700;
- if (lgRunningSystem7) {
- /* We are happy */
- *gWorldAvailable = true;
- return (noErr);
- }
-
- /* Running System 6. Check for 32-bit Quickdraw */
- err = Gestalt (gestaltQuickdrawVersion, &gestaltResponse);
- if (err != noErr) return (err);
- if (gestaltResponse & gestalt32BitQD) *gWorldAvailable = true;
- return (noErr);
- }
-
- /*=================================================================================================
- /* FreeOffscreen
- /*
- /* Free the offscreen GWorld.
- /*-------------------------------------------------------------------------------------------------*/
- pascal void FreeOffscreen (GWorldPtr offscreenGWorld)
- {
- if (offscreenGWorld != nil) DisposeGWorld (offscreenGWorld);
- }
-
- /*=================================================================================================
- /* CheckOffscreen
- /*
- /* Check if a new GWorld needs to be reallocated because the window has been moved
- /* or bit-depth has been changed. Routine will also allocate a new GWorld if the
- /* variable offscreenGWorld doesn't have one yet (i.e. offscreenGWorld is nil).
- /* If a GWorld cannot be made, offscreenGWorld is set to nil.
- /*
- /* Call this routine any time to make sure offscreenGWorld has the right configuration.
- /*-------------------------------------------------------------------------------------------------*/
- pascal QDErr CheckOffscreenForWindow (GWorldPtr *offscreenGWorld,
- short pixelDepth,
- WindowPtr window)
- {
- Rect boundsRect;
- QDErr err;
- GWorldFlags newFlags;
-
- boundsRect = window->portRect;
-
- if (pixelDepth == 0) {
- /* boundsRect has to be in global coordinate (IM6 p. 21-13) */
- GrafPtr savedPort;
- GetPort (&savedPort);
- SetPort (window);
- LocalToGlobalRect (&boundsRect);
- SetPort (savedPort);
- }
-
- if (*offscreenGWorld == nil) {
- /* No GWorld yet. Allocate a new one */
- err = NewGWorld (offscreenGWorld, pixelDepth, &boundsRect,
- (CTabHandle) nil, (GDHandle) nil, (GWorldFlags) 0);
- return (err);
- } else {
- /* There is an existing GWorld */
-
- #if qDebug
- GWorldPtr oldGWorld = *offscreenGWorld;
- #endif
-
- /* Check if offscreen GWorld needs to be reallocated */
- newFlags = UpdateGWorld (offscreenGWorld, pixelDepth, &boundsRect,
- (CTabHandle) nil, (GDHandle) nil, (GWorldFlags) 0);
- if (newFlags & (1L<<gwFlagErrBit)) return ((long) newFlags);
-
- #if qDebug
- if (StripAddress (oldGWorld) != StripAddress(*offscreenGWorld)) MessageAlert ("\pNew GWorld was reallocated");
- #endif
-
- return ((*offscreenGWorld == nil) ? memFullErr : noErr);
- }
- }
-
- /*=================================================================================================
- /* BeginDrawingOffscreen
- /*
- /* Call this to redirect drawings to an offscreen GWorld. Finish redirection
- /* by calling EndDrawingOffscreen.
- /* Note the different ways of accessing the pixMap of a GWorld depending on
- /* whether System 6 or 7 is running. Read IM6 p. 21-19 very carefully!
- /* Note also that GetGWorldPixMap() could return a bitMap instead of a pixMap
- /* behind your back (e.g. on a PowerBook 100).
- /*-------------------------------------------------------------------------------------------------*/
- pascal void BeginDrawingOffscreen (GWorldPtr offscreenGWorld, WindowPtr window)
- {
- #pragma unused(window) /* Suppresses warning in MPW since THINK C requires "window" to be named */
-
- if (offscreenGWorld != nil) {
- GetGWorld (&lgSavedPort, &lgSavedGDH);
-
- /* lock the offscreen pixels down! */
- if (lgRunningSystem7) {
- /* Note getting the offScreenPixMap the proper way */
- if (!LockPixels (GetGWorldPixMap (offscreenGWorld))) {
- DebugMessage ("\pBeginDrawingOffscreen: LockPixels failed");
- }
- } else {
- /* Note getting the offScreenPixMap by dereferencing offscreenGWorld. Not as
- * clean but GetGWorldPixMap is not available in Sys 6. */
- if (!LockPixels (offscreenGWorld->portPixMap)) {
- DebugMessage ("\pBeginDrawingOffscreen: LockPixels failed");
- }
- }
-
- /* Redirect drawings offscreen only if pixels are locked down */
- SetGWorld (offscreenGWorld, (GDHandle) nil);
- }
- }
-
- /*=================================================================================================
- /* EndDrawingOffscreen
- /*
- /* End redirecting drawing to an offscreen GWorld and copy the GWorld to the window.
- /*-------------------------------------------------------------------------------------------------*/
- pascal void EndDrawingOffscreen (GWorldPtr offscreenGWorld, WindowPtr window)
- {
- if (offscreenGWorld != nil) {
- /* End redirection of drawings to offscreenGWorld */
- SetGWorld (lgSavedPort, lgSavedGDH);
-
- /* Make sure CopyBits is happy.
- * Specifically, if foreColor and bkColor are not (0,0,0) and (0xffff, 0xffff, 0xffff)
- * CopyBits will "colorize" instead of doing a straight copy. */
- ForeColor (blackColor);
- BackColor (whiteColor);
-
- if (lgRunningSystem7) {
- /* Get the offScreenPixMap the proper way */
- PixMapHandle offScreenPixMap = GetGWorldPixMap (offscreenGWorld);
- /* Note pixMap should still be locked */
- CopyBits ((BitMap *) *offScreenPixMap, &window->portBits,
- &offscreenGWorld->portRect, &window->portRect, srcCopy, nil);
- UnlockPixels (offScreenPixMap);
- } else {
- /* Get the offScreenPixMap by dereferencing offscreenGWorld. Not as
- * clean but GetGWorldPixMap is not available in Sys 6 */
- CopyBits (&((GrafPtr) offscreenGWorld)->portBits, &window->portBits,
- &offscreenGWorld->portRect, &window->portRect, srcCopy, nil);
- UnlockPixels (offscreenGWorld->portPixMap);
- }
- }
- }
-